#include "game_engine.h"

bool gameEngine_checkCollision(GameEngine* gameEngine, u16 x, u16 y, BoundingBox* boundingBox, u32 check)
{
	return gameEngine->checkCollision(x, y, boundingBox, check);
}

GameEngine::GameEngine(SDL_Surface* screen)
{
	srf_screen=screen;
}

void GameEngine::addTerrainPartSpecs(u16 x, u16 y, u16 width, u16 height, BoundingBox* boundingBox)
{
	TerrainPartSpecs specs;
	SDL_Rect clip;
	clip.x=x;
	clip.y=y;
	clip.w=width;
	clip.h=height;
	specs.clip=clip;
	specs.boundingBox=boundingBox;
	terrainPartsAvailable.push_back(specs);
}

void GameEngine::addTerrainPartInstance(s32 x, s32 y, u16 identifier)
{
	TerrainPartInstance instance;
	instance.x=x;
	instance.y=y;
	instance.terrainPartSpecsIdentifier=identifier;
	terrainPartInstances.push_back(instance);
}

void GameEngine::setTileset(SDL_Surface* tileset)
{
	srf_tileset=tileset;
}

void GameEngine::applyGraphics()
{
	// Terrain part instances
	{
		// Get terrain part instance vector size
		u16 terrainPartInstancesSize=terrainPartInstances.size();

		// Loop through terrain part instance vector
		for (u16 i=0; i<terrainPartInstancesSize; i++)
		{
			// Get identifier
			u16 j=terrainPartInstances[i].terrainPartSpecsIdentifier;

			// Get specs
			SDL_Rect clip=terrainPartsAvailable[j].clip;
			u16 x=terrainPartInstances[i].x;
			u16 y=terrainPartInstances[i].y;

			// Draw
			gfx_applySurface(x, y, srf_tileset, srf_screen, &clip);
		}
	}

	// Character instances
	{
		// Apply character graphics
		u16 characterInstancesSize=characterInstances.size();

		// Loop through character instance vector
		for (u16 i=0; i<characterInstancesSize; i++)
		{
			// Draw
			gfx_applySurface(characterInstances[i]->x, characterInstances[i]->y, characterInstances[i]->currentImage, srf_screen);
		}
	}

}

bool GameEngine::checkCollision(u16 x, u16 y, BoundingBox* boundingBox, u32 check)
{
	// Rename stuff *CHANGE THIS TO #DEFINES FOR SLIGHT OPTIMIZATION*
		// Bounding box
		BoundingBox* bbox1=boundingBox;

		// Coordinates
		u16 x1=x;
		u16 y1=y;

	// If check terrain part instances
	if (check&COLLISION_TERRAIN)
	{
		// Get size of terrain part instance vector
		u16 size=terrainPartInstances.size();

		// Loop through every terrain part
		for (u16 i=0; i<size; i++)
		{
			// Get tarrain part bounding box
			BoundingBox* bbox2=NULL;
			bbox2=terrainPartsAvailable[terrainPartInstances[i].terrainPartSpecsIdentifier].boundingBox;

			// Get terrain part instance coordinates
			s32 x2=terrainPartInstances[i].x;
			s32 y2=terrainPartInstances[i].y;

			// If collision
			if ((bbox1->rectLeft+bbox1->rectWidth+x1>bbox2->rectLeft+x2)&&(bbox1->rectLeft+x1<bbox2->rectLeft+bbox2->rectWidth+x2)
			&&(bbox1->rectTop+bbox1->rectHeight+y1>bbox2->rectTop+y2)&&(bbox1->rectTop+y1<bbox2->rectTop+bbox2->rectHeight+y2))
			{
				// Return collision
				return true;
			}
		}
	}

	// Return not collision
	return false;
}

u16 GameEngine::addCharacterInstance(CharacterType type, s32 x, s32 y, s16 direction)
{
	u16 identifier=(u16) characterInstances.size();
	Character* character=NULL;
	character=new Character(type, x, y, direction, this);
	characterInstances.push_back(character);
	return identifier;
}

void GameEngine::iterateCharacters()
{
	u16 size=characterInstances.size();
	for(u16 i=0; i<size; i++)
	{
		characterInstances[i]->iterate();
	}
}

bool GameEngine::loadStage(const char* path)
{
	// Open file
	FILE* file=fopen(path, "r");

	// If no error
	if (file!=NULL)
	{
		// Obtain file size
		fseek(file, 0, SEEK_END);
		s32 size=ftell(file);
		rewind(file);

		// Allocate memory to contain the file
		char* buffer=(char*) malloc(sizeof(char)*size);

		// Copy the file into the buffer:
		fread(buffer, 1, size , file);

		// Read the file
			//
			u32 index=0;

			while (true)
			{
				/*char readBuffer[32];
				while (true)
				{
					index++;
				}*/

				index++;
				if (index>size)
				{
					break;
				}
			}

		// Free buffer
		free(buffer);

		// Close file
		fclose(file);

		// Report success
		return true;
	}
	// If error
	else
	{
		// Report error
		return false;
	}
}
